#!/usr/bin/env python

# Copyright (c) 2009, Purdue University
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice, this
# list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# Neither the name of the Purdue University nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Make zone tool for dnsmanagement"""


__copyright__ = 'Copyright (C) 2009, Purdue University'
__license__ = 'BSD'
__version__ = '#TRUNK#'


import sys

from roster_user_tools import cli_common_lib
from roster_user_tools import roster_client_lib
from roster_user_tools.action_flags import Make
from roster_user_tools.data_flags import Zone


class Args(Make, Zone):
  pass


def main(args):
  """Collects command line arguments.

  Inputs:
    args: list of arguments from the command line
  """
  command = None
  if( args and not args[0].startswith('-') ):
    command = args.pop(0)
  usage = ('\n'
           '\n'
           'To make forward zones:\n'
           '\t%s forward -z <zone-name> -v <view-name> --origin <origin>\n'
           '\t-t <type> [-o <options>]\n'
           '\n'
           'To make reverse zones:\n'
           '\t%s reverse -z <zone-name> -v <view-name> -t <type>\n'
           '\t(--origin <origin> | --cidr-block <cidr-block>)\n'
           '\t[-o <options>]\n' % (
               tuple([sys.argv[0] for _ in range(2)])))
  args_instance = Args(command, ['forward', 'reverse'], args, usage)
  options = args_instance.options

  try:
    cli_common_lib.CliCommonLib(options)
  except cli_common_lib.ArgumentError, error:
    print 'ERROR: %s' % error
    sys.exit(1)

  if( options.view_name == 'any' ):
    cli_common_lib.DnsError('Cannot make view "any"', 1)

  if( options.origin and not options.origin.endswith('.') ):
    cli_common_lib.DnsError('Zone origin must terminate with "."', 1)

  if( options.options and options.file_name ):
    cli_common_lib.DnsError('Cannot supply both the -o/--options and '
                            'the -f/--file flag.', 1)

  if( options.file_name ):
    file_handle = open(options.file_name, 'r')
    options.options = file_handle.read().strip('\n')
    file_handle.close()

  views = roster_client_lib.RunFunction(
      u'ListViews', options.username, credfile=options.credfile,
      credstring=options.credstring, kwargs={u'view_name': options.view_name},
      server_name=options.server)['core_return']
  if( options.view_name not in views and options.view_name ):
    cli_common_lib.DnsError('The view specified does not exist.', 1)

  if( command == 'reverse' ):
    reverse_range_zone_assignments = roster_client_lib.RunFunction(
        u'ListReverseRangeZoneAssignments', options.username,
        credfile=options.credfile, credstring=options.credstring,
        server_name=options.server,
        kwargs={'zone_name': options.zone_name,
                'cidr_block': options.cidr_block})['core_return']

    if( options.cidr_block ):
      options.origin = roster_client_lib.RunFunction(
          u'ReverseIP', options.username, credfile=options.credfile,
          credstring=options.credstring, args=[options.cidr_block],
          server_name=options.server)['core_return']
    elif( options.origin ):
      options.cidr_block = roster_client_lib.RunFunction(
          u'UnReverseIP', options.username, credfile=options.credfile,
          credstring=options.credstring, args=[options.origin],
          server_name=options.server)['core_return']

    roster_client_lib.RunFunction(
        u'MakeZone', options.username, credfile=options.credfile,
        credstring=options.credstring,
        args=[options.zone_name, options.type, options.origin],
        kwargs={u'view_name': options.view_name,
                u'zone_options': options.options,
                u'make_any': options.dont_make_any},
        server_name=options.server)
    if( not options.quiet ):
      print ('ADDED REVERSE ZONE: zone_name: %s zone_type: %s '
             'zone_origin: %s zone_options: %s view_name: %s' % (
                 options.zone_name, options.type,
                 options.origin, options.options,
                 options.view_name))

    if( len(reverse_range_zone_assignments) == 0 and
        options.type.lower() != 'slave' ):
      roster_client_lib.RunFunction(
          u'MakeReverseRangeZoneAssignment', options.username,
          credfile=options.credfile, credstring=options.credstring,
          server_name=options.server,
          args=[options.zone_name, options.cidr_block])
      if( not options.quiet ):
        print ('ADDED REVERSE RANGE ZONE ASSIGNMENT: zone_name: %s '
               'cidr_block: %s ' % (
                   options.zone_name, options.cidr_block))

  elif( command == 'forward' ):
    if( options.bootstrap_zone ):
      zone_bootstrap_dict = {'name_server': options.bootstrap_nameserver,
                             'admin_email': options.bootstrap_admin_email}
      soa_dict, ns_dict = roster_client_lib.RunFunction(
          u'BootstrapZone', options.username, credfile=options.credfile,
          credstring=options.credstring,
          args=[options.zone_name, options.type, options.origin, 
                options.view_name, zone_bootstrap_dict],
          kwargs={u'zone_options': options.options,
                  u'make_any': options.dont_make_any},
          server_name=options.server)['core_return']

      soa_serial_number = roster_client_lib.RunFunction(
          u'ListRecords', options.username, credfile=options.credfile,
          credstring=options.credstring,
          kwargs={'record_type': u'soa', 
                  'target': u'@',
                  'zone_name': options.zone_name, 
                  'view_name': options.view_name},
          server_name=options.server)['core_return'][0]['serial_number']
      if( not options.quiet ):
        print ('ADDED FORWARD ZONE: zone_name: %s zone_type: %s '
               'zone_origin: %s zone_options: %s view_name: %s' % (
                   options.zone_name, options.type,
                   options.origin, options.options,
                   options.view_name))
        print ('ADDED SOA: @ zone_name: %s view_name: %s ttl: %s '
               'refresh_seconds: %s expiry_seconds: %s name_server: %s '
               'minimum_seconds: %s retry_seconds: %s serial_number: %s '
               'admin_email: %s') % (options.zone_name, options.view_name,
                   soa_dict['ttl'], soa_dict['refresh_seconds'], 
                   soa_dict['expiry_seconds'], soa_dict['name_server'],
                   soa_dict['minimum_seconds'], soa_dict['retry_seconds'],
                   soa_serial_number, soa_dict['admin_email'])
        print ('ADDED NS: @ zone_name: %s view_name: %s ttl: %s '
               'name_server: %s') % (options.zone_name, options.view_name,
                   ns_dict['ttl'], ns_dict['name_server'])
    else:
      roster_client_lib.RunFunction(
          u'MakeZone', options.username, credfile=options.credfile,
          credstring=options.credstring,
          args=[options.zone_name, options.type, options.origin],
          kwargs={u'view_name': options.view_name,
                  u'zone_options': options.options,
                  u'make_any': options.dont_make_any},
          server_name=options.server)
      if( not options.quiet ):
        print ('ADDED FORWARD ZONE: zone_name: %s zone_type: %s '
               'zone_origin: %s zone_options: %s view_name: %s' % (
                   options.zone_name, options.type,
                   options.origin, options.options,
                   options.view_name))
  else:
    cli_common_lib.DnsError(
        'Command %s exists, but codepath doesn\'t.' % command, 1)

if __name__ == "__main__":
  main(sys.argv[1:])
